use crate::mesh::Vertex;

pub struct Instance {
    pub position: cgmath::Vector3<f32>,
    pub rotation: cgmath::Quaternion<f32>
}

impl Instance {
    pub fn to_raw(&self) -> InstanceRaw {
        InstanceRaw {
            model_mat: (cgmath::Matrix4::from_translation(self.position) * cgmath::Matrix4::from(self.rotation)).into()
        }
    }
}

#[repr(C)]
#[derive(Clone, Copy, bytemuck::Zeroable, bytemuck::Pod)]
pub struct InstanceRaw {
    model_mat: [[f32; 4]; 4]
}

impl Vertex for InstanceRaw {
    fn layout() -> &'static wgpu::VertexBufferLayout<'static> {
        const LAYOUT: wgpu::VertexBufferLayout = wgpu::VertexBufferLayout {
            array_stride: std::mem::size_of::<InstanceRaw>() as wgpu::BufferAddress,
            step_mode: wgpu::VertexStepMode::Instance,
            attributes: &wgpu::vertex_attr_array![
                5 => Float32x4,
                6 => Float32x4,
                7 => Float32x4,
                8 => Float32x4
            ]
        };

        &LAYOUT
    }
}

pub struct InstanceArray {
    pub layout: &'static wgpu::VertexBufferLayout<'static>,
    pub buffer: wgpu::Buffer,
    pub cnt: u32
}

impl InstanceArray {
    pub fn from_data<I: Vertex>(device: &wgpu::Device, data: &[I]) -> Self {
        use wgpu::util::DeviceExt;

        let layout = I::layout();

        let buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
                label: Some("Instance Buffer"),
                contents: bytemuck::cast_slice(data),
                usage: wgpu::BufferUsages::VERTEX
            }
        );

        let cnt = data.len() as u32;

        Self {
            layout,
            buffer,
            cnt
        }
    }
}
